﻿#region Namespace References

using System;
using DynConDevCorp.OpenArch.SmartData.Interfaces;
using DynConDevCorp.OpenArch.SmartData.Interfaces.EventArgClasses;

#endregion

namespace DynConDevCorp.OpenArch.SmartData.Core
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class SmartEffect : ISmartEffect
    {
        /// <summary>
        /// Executes Effect if the Cause is in the trigger set.
        /// </summary>
        /// <param name="cause">The cause.</param>
        public abstract void Execute(EffectCauses cause);

        #region ISmartEffect Members


        /// <summary>
        /// Gets or sets the triggerable causes.
        /// </summary>
        /// <value>The triggerable causes.</value>
        public EffectCauses TriggerableCauses { get; protected set;}

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TData">The type of the AT a_ TYPE.</typeparam>
    public class SmartEffect<TData> : SmartEffect, ISmartEffect<TData>
    {
        private bool ActiveCause(EffectCauses cause)
        {
            return (TriggerableCauses & cause) != 0;

        }
        public override void Execute(EffectCauses cause)
        {
            if (!ActiveCause(cause))
                return;

            ValueChangedEventArgs<TData> args = new ValueChangedEventArgs<TData>(null, String.Empty, default(TData), default(TData));
            if (m_Target != null)
                m_Target(null, args);
        }

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SmartEffect&lt;TDATA&gt;"/> class.
        /// </summary>
        /// <param name="target">The target.</param>
        public SmartEffect(EventHandler<ValueChangedEventArgs<TData>> target)
        {
            TriggerableCauses = EffectCauses.ValueChanged;
            m_Target = target;
        }

        #endregion

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
        public override bool Equals(object obj)
        {
            SmartEffect<TData> otherEffect = obj as SmartEffect<TData>;
            if (otherEffect == null)
                return false;
            bool sameTarget = ReferenceEquals(m_Target, otherEffect.m_Target);
            bool equalTargets = m_Target == otherEffect.m_Target;
            return (sameTarget | equalTargets);
        }

        
        #region Public Instance Methods

        /// <summary>
        /// Fires the specified sender.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The args.</param>
        public void InvokeEffect(Object sender, ValueChangedEventArgs<TData> args)
        {
            if (!ActiveCause(args.EffectCause))
                return;

            if (m_Target != null)
                m_Target(sender, args);
        }

        #endregion

        #region Fields and Constants

        private readonly EventHandler<ValueChangedEventArgs<TData>> m_Target;

        #endregion
    }
}